from django.views import View
from django.shortcuts import render
from django.http import JsonResponse
from django.utils.safestring import mark_safe
from django.http import QueryDict
from web.forms.issue import IssueModelForm
from web.forms.issue import IssueReplayModel
from web.forms.issue import InviteModelForm
from utils.pagination import Pagination
from utils.encrypt import uid
from web import models
from django.views.decorators.csrf import csrf_exempt
import json

class CheckFilter(object):
    '''
    可迭代对象

    '''
    def __init__(self,name,data_list,request):
        self.name=name
        self.data_list=data_list
        self.request=request

    def __iter__(self):
        for item in self.data_list:
            key=str(item[0])
            text=item[1]
            ck=''
            value_list=self.request.GET.getlist(self.name)
            if key in value_list:
                ck='checked'
                value_list.remove(key)
            else:
                value_list.append(key)
            query_dict=self.request.GET.copy()
            query_dict._mutable=True
            query_dict.setlist(self.name,value_list)
            if 'page' in query_dict:
                query_dict.pop('page')
            param_url=query_dict.urlencode()
            if param_url:
                url='{}?{}'.format(self.request.path_info,param_url)
            else:
                url=self.request.path_info
            tpl='<a class="cell" href="{url}"><input type="checkbox" {ck} /><label>{text}</label></a>'
            html=tpl.format(url=url,ck=ck,text=text)
            yield mark_safe(html)

class SelectFilter(object):
    def __init__(self,name,data_list,request):
        self.name=name
        self.data_list=data_list
        self.request=request
    def __iter__(self):
        yield mark_safe("<select class='select2' multiple='multiple' style='width:100%;'>")
        for item in self.data_list:

            key=str(item[0])
            text=item[1]
            selected=''
            value_list=self.request.GET.getlist(self.name)
            if key in value_list:
                selected='selected'
                value_list.remove(key)
            else:
                value_list.append(key)
            query_dict=self.request.GET.copy()
            query_dict._mutable=True
            query_dict.setlist(self.name,value_list)

            if 'page' in query_dict:
                query_dict.pop('page')
            param_url=query_dict.urlencode()
            if param_url:
                url='{}?{}'.format(self.request.path_info,param_url)
            else:
                url=self.request.path_info
            html='<option value="{url}" {selected}>{text}</option>'.format(url=url,selected=selected,text=text)
            yield mark_safe(html)
        yield mark_safe('</select>')
class IssueView(View):

    def get(self,request,project_id):
        ck_obj=CheckFilter('status',models.Issues.status_choices,request)
        allow_filter_name=['issues_type','status','priority','assign','attention']
        condition={}
        # print(request.GET.getlist('status'))
        for name in allow_filter_name:
            value_list=request.GET.getlist(name)
            if not value_list:
                continue
            condition['{}__in'.format(name)]=value_list
        # print(condition)
        queryset=models.Issues.objects.filter(project=request.tracer.project).filter(**condition)
        page_object=Pagination(current_page=request.GET.get('page'),all_count=queryset.count(),base_url=request.path_info,query_params=request.GET,per_page=3,pager_page_count=5)
        issues_object_list=queryset[page_object.start:page_object.end]
        form=IssueModelForm(request)
        project_issues_type=models.IssuesType.objects.filter(project_id=project_id).values_list('id','title')
        project_total_user=[[request.tracer.project.creator_id,request.tracer.project.creator.username],]
        join_user=models.ProjectUser.objects.filter(project_id=project_id).values_list('user_id','user__username')
        project_total_user.extend(join_user)
        invite_form=InviteModelForm()
        context={
            'form':form,
            'invite_form':invite_form,
            'issues_object_list': issues_object_list,
            'page_html': page_object.page_html(),
            'filter_list':[
                {'title':'问题类型','filter':CheckFilter('issues_type',project_issues_type,request)},
                {'title': "状态", 'filter': CheckFilter('status', models.Issues.status_choices, request)},
                {'title':'优先级','filter':CheckFilter('priority',models.Issues.priority_choices,request)},
                {'title': "指派者", 'filter': SelectFilter('assign', project_total_user, request)},
                {'title': "关注者", 'filter': SelectFilter('attention', project_total_user, request)},
                           ],
        }
        return render(request,'web/issues.html',context)

    def post(self,request,project_id):
        form=IssueModelForm(request,data=request.POST)
        if form.is_valid():
            form.instance.project=request.tracer.project
            form.instance.creator=request.tracer.user
            form.save()
            return JsonResponse({'status':True})
        else:
            return JsonResponse({'status':False,'error':form.errors})


class IssuesDetailView(View):
    '''
    问题的编辑页面
    '''
    def get(self,request,project_id,issues_id):
        issues_object=models.Issues.objects.filter(project=request.tracer.project,id=issues_id).first()
        form=IssueModelForm(request,instance=issues_object)
        return render(request,'web/issues_detail.html',{'form':form,'issues_object':issues_object})


class IssuesRecordView(View):
    '''
    问题的回复记录
    '''
    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super(IssuesRecordView, self).dispatch(request,*args,**kwargs)

    def get(self,request,project_id,issues_id):
        reply_list = models.IssuesReply.objects.filter(issues_id=issues_id, issues__project=request.tracer.project)
        # 将queryset转换为json格式
        data_list = []
        for row in reply_list:
            data = {
                'id': row.id,
                'reply_type_text': row.get_reply_type_display(),
                'content': row.content,
                'creator': row.creator.username,
                'datetime': row.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': row.reply_id
            }
            data_list.append(data)
        return JsonResponse({'status': True, 'data': data_list})

    def post(self,request,project_id,issues_id):
        form=IssueReplayModel(request.POST)
        if form.is_valid():
            form.instance.issues_id = issues_id
            form.instance.reply_type = 2
            form.instance.creator = request.tracer.user
            instance = form.save()
            info = {
                'id': instance.id,
                'reply_type_text': instance.get_reply_type_display(),
                'content': instance.content,
                'creator': instance.creator.username,
                'datetime': instance.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': instance.reply_id
            }

            return JsonResponse({'status': True, 'data': info})
        return JsonResponse({'status': False, 'error': form.errors})

class IssuesChangeView(View):
    '''
    问题详情变化时触发的视图
    '''
    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)

    def create_reply_record(self,request,issues_object,change_record):
        new_object = models.IssuesReply.objects.create(
            reply_type=1,
            issues=issues_object,
            content=change_record,
            creator=request.tracer.user,
        )
        new_reply_dict = {
            'id': new_object.id,
            'reply_type_text': new_object.get_reply_type_display(),
            'content': new_object.content,
            'creator': new_object.creator.username,
            'datetime': new_object.create_datetime.strftime("%Y-%m-%d %H:%M"),
            'parent_id': new_object.reply_id
        }
        return new_reply_dict
    def post(self,request,project_id,issues_id):
        post_dict=json.loads(str(request.body,encoding='utf8')) #{'name': 'subject', 'value': '任务1-1'}
        issues_object=models.Issues.objects.filter(id=issues_id,project=request.tracer.project).first()
        name=post_dict.get('name')
        value=post_dict.get('value')
        field_object=issues_object._meta.get_field(name)#web.Issues.subject
        #选择的是文本的情况
        if name in ["subject", 'desc', 'start_date', 'end_date']:
            #前端获得的值为空
            if not value:
                #数据库中该字典的值不能为空

                if not field_object.null:
                    return JsonResponse({'status':False,'error':'您选择的值不能为空'})
                #数据库中该字段的值可以为空
                else:
                    #更新该字段的值
                    setattr(field_object,name,None)
                    #保存到数据库
                    issues_object.save()
                    #返回给前端的前端的记录值 & 存入到 问题更新记录的值
                    change_record='{}更新为空'.format(field_object.verbose_name)
            #前端获取的值不为空
            else:
                setattr(issues_object,name,value)

                issues_object.save()
                change_record='{}更新为{}'.format(field_object.verbose_name,value)
            return JsonResponse({'status':True,'data':self.create_reply_record(request,issues_object,change_record)})

        #选择的是fk的情况
        if name in ['issues_type', 'module', 'parent', 'assign']:
            #用户提交的值为空
            if not value:
                #该字段不能为空
                if not field_object.null:
                    return JsonResponse({'status':False,'error':'您选择的值不能为空'})
                #该字段可以为空
                else:
                    setattr(field_object,name,None)
                    issues_object.save()
                    change_record='{}更新为空'.format(field_object.verbose_name)
            #用户提交的值不为空
            else:
                if name=='assign':
                    #如果指派的人是创建者
                    if value==str(request.tracer.project.creator_id):
                        instance=request.tracer.project.creator
                    else:
                       #如果指派的人是参与者
                        project_user_object=models.ProjectUser.objects.filter(project_id=project_id,user_id=value).first()
                        if project_user_object:
                            instance=project_user_object.user
                        #如果指派的人不是参与者
                        else:
                            instance=None
                    setattr(issues_object,name,instance)
                    issues_object.save()
                    change_record='{}更新为{}'.format(field_object.verbose_name,str(instance))
                else:
                    instance=field_object.remote_field.model.objects.filter(id=value,project_id=project_id).first()
                    if not instance:
                        return JsonResponse({'status': False, 'error': '您选择的值不存在'})
                    setattr(issues_object,name,instance)
                    issues_object.save()
                    change_record='{}更新为{}'.format(field_object.verbose_name,str(instance))

            return JsonResponse({'status': True, 'data': self.create_reply_record(request, issues_object, change_record)})

        #选择的是choices 字段
        if name in ['priority', 'status', 'mode']:
            selected_text=None
            for key,text in field_object.choices:
                if str(key)==value:
                    selected_text=text
            if not selected_text:
                return JsonResponse({'status':False,'error':'您选择的值不存在'})
            setattr(issues_object,name,value)
            issues_object.save()
            change_record='{}更新为{}'.format(field_object.verbose_name,selected_text)
            return JsonResponse(
                {'status': True, 'data': self.create_reply_record(request, issues_object, change_record)})
        #选择的是m2m 字段
        if name =='attention':
            # print(post_dict){'name': 'attention', 'value': ['2']}
            if not isinstance(value,list):
                return JsonResponse({'status': False, 'error': '数据格式错误'})
            if not value:
                issues_object.attention.set(value)
                issues_object.save()
                change_record='{}更新为空'.format(field_object.verbose_name)
            else:
                user_dict={str(request.tracer.project.creator_id):request.tracer.project.creator.username}
                for item in models.ProjectUser.objects.filter(project_id=project_id):
                    user_dict[str(item.user_id)]=item.user.username
                username_list=[]
                for user_id in value:
                    username=user_dict.get(str(user_id))
                    if not username:
                        return JsonResponse({'status':False,'error':'用户不存在 请重新设置'})
                    username_list.append(username)
                issues_object.attention.set(value)
                issues_object.save()
                change_record='{}更新为{}'.format(field_object.verbose_name,''.join(username_list))
            return JsonResponse(
                {'status': True, 'data': self.create_reply_record(request, issues_object, change_record)})

        return JsonResponse({'status': False, 'error': "滚"})

class ProjectInviteView(View):
    '''
    点击生成邀请码的处理
    '''
    def post(self,request,project_id):
        form=InviteModelForm(request.POST)
        if form.is_valid():
            #only the project creator can generate the link
            #create random invite code
            #save the invite code to database
            #return the invite lin to web
            if request.tracer.user !=request.tracer.project.creator:
                form.add_error('period','only the project creator can genrate the link')
                return JsonResponse({'status':False,'error':form.errors})
            form.instance.project=request.tracer.project
            form.instance.code=uid(request.tracer.user.mobile_phone)
            form.instance.creator=request.tracer.user
            form.save()
            from django.urls import reverse

            url='{scheme}://{host}{path}'.format(
                scheme=request.scheme,host=request.get_host(),
                path=reverse('web:invite_join',
                             kwargs={'code':form.instance.code}))
            return JsonResponse({'status':True,'data':url})
        return JsonResponse({'status':False,'error':form.errors})
class InviteJoinView(View):
    '''
    处理邀请链接的视图
    '''
    def get(self,request,code):
        #获取当前时间
        import datetime
        current_datetime=datetime.datetime.utcnow()
        #查看项目邀请码是否正确
        invite_obj=models.ProjectInvite.objects.filter(code=code).first()
        if not invite_obj:
            return render(request, 'web/invite_join.html',{'error':'邀请码不存在'})
        #查看该邀请码对应的项目是否时当前的登录用户创建的
        if invite_obj.project.creator==request.tracer.user:
            return render(request, 'web/invite_join.html', {'error': '您已经在项目中了 无需参与'})
        #查看项目是否被登录者参与
        exists=models.ProjectUser.objects.filter(project=invite_obj.project,user=request.tracer.user).exists()
        if exists:
            return render(request, 'web/invite_join.html', {'error': '您已经在项目中了 无需参与'})
        #查看是否时免费用户
        max_transaction=models.Transaction.objects.filter(user=request.tracer.user).order_by('-id').first()
        if max_transaction.price_policy.category==1:
            max_member = max_transaction.price_policy.project_member
        else:
            #该项目的付费时间已经到期
            if max_transaction.end_datetime<current_datetime:
                free_object = models.PricePolicy.objects.filter(category=1).first()
                max_member = free_object.project_member
            #该项目的付费时间没有到期
            else:
                max_member = max_transaction.price_policy.project_member
        #查看项目的成员数据是否超过套餐的数据
        current_member=models.ProjectUser.objects.filter(project=request.tracer.project).count()
        current_member=current_member+1
        if current_member>max_member:
            return render(request, 'web/invite_join.html', {'error': '项目成员超限，请升级套餐'})
        #查看邀请码是否过期
        limit_datetime = invite_obj.create_datetime + datetime.timedelta(minutes=invite_obj.period)

        print(limit_datetime)
        print(current_datetime)
        if current_datetime>limit_datetime:
            return render(request, 'web/invite_join.html', {'error': '邀请码已经过期'})
        # 查看邀请码是否有数量限制
        if invite_obj.count:
            if invite_obj.use_count >= invite_obj.count:
                return render(request, 'invite_join.html', {'error': '邀请码数据已使用完'})
            else:
                #保存数据 把用的数量＋1
                invite_obj.use_count += 1
                invite_obj.save()
        #更新项目的参与成员
        models.ProjectUser.objects.create(user=request.tracer.user, project=invite_obj.project)
        invite_obj.project.join_count += 1
        invite_obj.project.save()
        return render(request,'web/invite_join.html',{'project':invite_obj.project})